package com.gitee.sergius.apitool.web.html;

import com.gitee.sergius.apitool.constant.Constant;
import com.gitee.sergius.apitool.entity.RequestParamEntity;
import com.gitee.sergius.apitool.entity.ResponseParamEntity;
import com.gitee.sergius.apitool.entity.StatusCodeEntity;
import com.gitee.sergius.apitool.constant.DataType;
import com.gitee.sergius.apitool.entity.SubEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * @author shawn yang
 * @version 1.0.0
 * <p><pre>用来生成API展示页面html</pre>
 *
 */
public class HtmlOperater {

    /**
     * 获取style部分
     */
    public static String getStylePart(){
        return  "<style>\n" +
                "        body {\n" +
                "            width: 80%;\n" +
                "            margin: 0 auto;\n" +
                "        }\n" +
                "        th {\n" +
                "            background-color: #cccccc;\n" +
                "        }\n" +
                "        tr:nth-child(even) {\n" +
                "            background: #F4F4F4;\n" +
                "        }\n" +
                "        .title-div {\n" +
                "            margin-bottom:5px;\n"+
                "            padding: 3px 10px;\n" +
                "            width: 100%;\n" +
                "            text-align: left;\n" +
                "            font-size: 18px;\n" +
                "        }\n" +
                "        .table-div {\n" +
                "            margin: 10px 10px 25px 10px;\n" +
                "        }\n" +
                "        .url-span {\n" +
                "            font: italic bold 12px/30px Georgia, serif;\n" +
                "        }\n" +
                "        .desc-span {\n" +
                "            font: 14px arial, sans-serif;\n" +
                "            margin: 5px 10px;\n" +
                "            float: right;\n" +
                "        }\n" +
                "        .text-div {\n" +
                "            padding: 10px;\n" +
                "            background-color: #F4F4F4;\n" +
                "        }\n" +
                "        caption {\n" +
                "            font: 17px arial, sans-serif;\n" +
                "        }\n" +
                "        .method-btn{\n" +
                "            padding:2px;\n" +
                "            width:50px;\n" +
                "            margin: 0px 15px;\n" +
                "        }\n" +
                "        .arraw-span{\n" +
                "            top:5px;\n" +
                "        }\n" +
                "        .tag-span{\n" +
                "            font-size: 15px;\n" +
                "            margin-right: 15px;\n" +
                "        }\n" +
                "        th{\n" +
                "            text-align: center;\n" +
                "        }\n" +
                "    </style>";
    }

    /**
     * 获取script部分
     */
    public static String getScriptPart(){
        return  "<script>\n" +
                "    $(function () {\n" +
                "        $('.title-div').click(function () {\n" +
                "            $(this).next().slideToggle(200);\n" +
                "            $(this).children('.glyphicon-chevron-up').toggle();\n" +
                "            $(this).children('.glyphicon-chevron-down').toggle();\n" +
                "        });\n" +
                "    })\n" +
                "</script>";
    }


    /**
     * 获取body部分
     * @param subEntity 接口封装实体
     */
    public static String getBodyPart(SubEntity subEntity){
        StringBuilder result = new StringBuilder();
        result.append(getUrlPart(subEntity));
        result.append(" <div style='display: none;'><br/>");

        result.append(getDescPart(subEntity));
        result.append(getInParamPart(subEntity));
        result.append(getOutParamPart(subEntity));
        result.append(getInExamplePart(subEntity));
        result.append(getOutExamplePart(subEntity));
        result.append(getExceptionPart(subEntity));

        result.append(" </div> ");
        return result.toString();
    }


    /**
     * 异常说明
     * @param subEntity 接口封装实体
     */
    private static StringBuilder getExceptionPart(SubEntity subEntity){
        StringBuilder reqHtml = new StringBuilder();

        List<StatusCodeEntity> statusCodeEntityList = subEntity.getStatusCodeEntityList();

        if(!CollectionUtils.isEmpty(statusCodeEntityList)){
            reqHtml.append(" <span class='glyphicon glyphicon-minus'>返回码说明</span> ")
                    .append(" <table class='table-div table table-bordered'> ")
                    .append(" <thead><tr><th>返回码</th><th>说明</th></tr></thead> ")
                    .append(" <tbody> ");
            for(StatusCodeEntity statusCodeEntity: statusCodeEntityList){
                reqHtml.append(" <tr><td>"+statusCodeEntity.getCode()+"</td><td>"+statusCodeEntity.getDesc()+"</td></tr> ");
            }
            reqHtml.append(" </tbody></table> ");
        }
        return reqHtml;
    }


    /**
     * 出参示例
     * @param subEntity 接口封装实体
     */
    private static StringBuilder getOutExamplePart(SubEntity subEntity){
        StringBuilder resHtml = new StringBuilder();
        List<ResponseParamEntity> responseParamEntityList = subEntity.getResponseParamEntityList();
        if(!CollectionUtils.isEmpty(responseParamEntityList)){
            boolean isBaseReturn = Constant.DEFAULT_UNDEFINE_NAME.equals(responseParamEntityList.get(0).getName());
            resHtml.append(" <span class='glyphicon glyphicon-minus'>出参示例</span> ");
            resHtml.append(" <div class='table-div'><div class='text-div'> ");
            if(!isBaseReturn){
                resHtml.append(" <p >{</p> ");
            }
            resHtml.append(getOutExampleRowPart(responseParamEntityList,isBaseReturn));
            if(!isBaseReturn) {
                resHtml.append(" <p >}</p> ");
            }
            resHtml.append(" </div></div> ");
        }
        return resHtml;
    }

    private static StringBuilder getOutExampleRowPart(List<ResponseParamEntity> responseParamEntityList,boolean isBaseReturn){
        StringBuilder html = new StringBuilder();
        if(!CollectionUtils.isEmpty(responseParamEntityList)) {
            for(int i=0,len = responseParamEntityList.size();i<len;i++){
                ResponseParamEntity entity = responseParamEntityList.get(i);
                String style = "style='text-indent: " + (entity.getLevel()) + "em;'";
                String name = entity.getName();
                String example = entity.getExample();
                String type = entity.getType();

                String nameHtml;
                if(isBaseReturn){
                    nameHtml = "";
                }else{
                    nameHtml = "\""+ name + "\":";
                }

                if(!entity.isHasChild()){
                    html.append(" <p " + style + ">" + nameHtml + getExampleHtml(type,example,entity.isArray()));
                }else{
                    if(!entity.isArray()){
                        html.append(" <p " + style + ">" + nameHtml + "{" + "</p>");
                        html.append(getOutExampleRowPart(entity.getChildList(),false));
                        html.append(" <p " + style + ">}");
                    }else{
                        html.append(" <p " + style + ">" + nameHtml + "[{" + "</p>");
                        html.append(getOutExampleRowPart(entity.getChildList(),false));
                        html.append(" <p " + style + ">},{...}]");
                    }
                }

                if(i==len-1){
                    html.append( "</p> ");
                }else{
                    html.append( ",</p> ");
                }

            }



        }
        return html;
    }


    /**
     * 入参示例
     * @param subEntity
     * @return
     */
    private static StringBuilder getInExamplePart(SubEntity subEntity){
        StringBuilder reqHtml = new StringBuilder();
        List<RequestParamEntity> requestParamEntityList = subEntity.getRequestParamEntityList();
        if(!CollectionUtils.isEmpty(requestParamEntityList)){
            boolean isBaseReturn = Constant.DEFAULT_UNDEFINE_NAME.equals(requestParamEntityList.get(0).getName());

            reqHtml.append(" <span class='glyphicon glyphicon-minus'>入参示例</span> ");
            reqHtml.append(" <div class='table-div'><div class='text-div'> ");
            if(!isBaseReturn){
                reqHtml.append(" <p >{</p> ");
            }
            reqHtml.append(getInExampleRowPart(requestParamEntityList,isBaseReturn));
            if(!isBaseReturn) {
                reqHtml.append(" <p >}</p> ");
            }
            reqHtml.append(" </div></div> ");
        }
        return reqHtml;
    }

    private static StringBuilder getInExampleRowPart(List<RequestParamEntity> requestParamEntityList,boolean isBaseReturn){
        StringBuilder html = new StringBuilder();
        if(!CollectionUtils.isEmpty(requestParamEntityList)) {
            for(int i=0,len = requestParamEntityList.size();i<len;i++){
                RequestParamEntity entity = requestParamEntityList.get(i);
                String style = "style='text-indent: " + (entity.getLevel()) + "em;'";
                String name = entity.getName();
                String example = entity.getExample();
                String type = entity.getType();

                String nameHtml;
                if(isBaseReturn){
                    nameHtml = "";
                }else{
                    nameHtml = "\""+ name + "\":";
                }

                if(!entity.isHasChild()){
                    html.append(" <p " + style + ">" + nameHtml + getExampleHtml(type,example,entity.isArray()));
                }else{
                    if(!entity.isArray()){
                        html.append(" <p " + style + ">" + nameHtml + "{" + "</p>");
                        html.append(getInExampleRowPart(entity.getChildList(),false));
                        html.append(" <p " + style + ">}");
                    }else{
                        html.append(" <p " + style + ">" + nameHtml + "[{" + "</p>");
                        html.append(getInExampleRowPart(entity.getChildList(),false));
                        html.append(" <p " + style + ">},{...}]");
                    }
                }

                if(i==len-1){
                    html.append( "</p> ");
                }else{
                    html.append( ",</p> ");
                }

            }



        }
        return html;
    }

    /**
     * 基础类型html
     * @param type
     * @param example
     * @param isArray
     */
    private static String getExampleHtml(String type,String example,boolean isArray){
        String result ;
        DataType[] dataTypes = DataType.values();
        DataType exampleType = DataType.OTHER;
        for(DataType dataType : dataTypes){
            if(dataType.getName().equals(type)){
                exampleType = dataType;
            }
        }
        if(StringUtils.isEmpty(example)){
            example = exampleType.getDefaultHtml();
        }

        if(exampleType.isWithQuotation()){
            example = "\"" + example + "\"";
        }

        if(!isArray){
            result = example;
        }else{
            result = "["+example+",...]";
        }
        return result;
    }

    /**
     * 出参说明
     * @param subEntity
     * @return
     */
    private static StringBuilder getOutParamPart(SubEntity subEntity){
        StringBuilder reqHtml = new StringBuilder();
        List<ResponseParamEntity> responseParamEntityList = subEntity.getResponseParamEntityList();
        if(!CollectionUtils.isEmpty(responseParamEntityList)){
            reqHtml.append(" <span class='glyphicon glyphicon-minus'>出参说明</span> ");
            reqHtml.append(" <table class='table-div table table-bordered'> ");
            reqHtml.append(" <thead><tr><th>参数名</th><th>类型</th><th>必填</th><th>说明</th></tr></thead><tbody> ");

            reqHtml.append(getOutParamTrPart(responseParamEntityList));

            reqHtml.append(" </tbody></table> ");
        }
        return reqHtml;
    }

    private static StringBuilder getOutParamTrPart(List<ResponseParamEntity> responseParamEntityList){
        StringBuilder html = new StringBuilder();
        if(!CollectionUtils.isEmpty(responseParamEntityList)) {
            for (ResponseParamEntity entity : responseParamEntityList) {
                String style = "style='text-indent: " + entity.getLevel()*2 + "em;'";
                String name = entity.getName();
                String type = entity.getType() + (entity.isArray() ? "[]" : "");
                String isRequired = (entity.isRequired() ? "是" : "否");
                String desc = entity.getDesc();
                if(Constant.DEFAULT_UNDEFINE_NAME.equals(name)){
                    name = "";
                    desc = "";
                }
                html.append(" <tr><td " + style + ">" + name + "</td><td>" + type + "</td><td>" + isRequired + "</td><td>" + desc + "</td></tr> ");
                if (entity.isHasChild()) {
                    html.append(getOutParamTrPart(entity.getChildList()));
                }
            }
        }
        return html;
    }

    /**
     * 入参说明
     * @param subEntity
     * @return
     */
    private static StringBuilder getInParamPart(SubEntity subEntity){
        StringBuilder reqHtml = new StringBuilder();
        List<RequestParamEntity> requestParamEntityList = subEntity.getRequestParamEntityList();
        if(!CollectionUtils.isEmpty(requestParamEntityList)){
            reqHtml.append(" <span class='glyphicon glyphicon-minus'>入参说明</span> ");
            reqHtml.append(" <table class='table-div table table-bordered'> ");
            reqHtml.append(" <thead><tr><th>参数名</th><th>类型</th><th>必填</th><th>说明</th></tr></thead><tbody> ");

            reqHtml.append(getInParamTrPart(requestParamEntityList));

            reqHtml.append(" </tbody></table> ");
        }

        return reqHtml;
    }

    private static StringBuilder getInParamTrPart(List<RequestParamEntity> requestParamEntityList){
        StringBuilder html = new StringBuilder();
        if(!CollectionUtils.isEmpty(requestParamEntityList)) {
            for (RequestParamEntity entity : requestParamEntityList) {
                String style = "style='text-indent: " + entity.getLevel()*2 + "em;'";
                String name = entity.getName();
                String type = entity.getType() + (entity.isArray() ? "[]" : "");
                String isRequired = (entity.isRequired() ? "是" : "否");
                String desc = entity.getDesc();
                if(Constant.DEFAULT_UNDEFINE_NAME.equals(name)){
                    name = "";
                    desc = "";
                }
                html.append(" <tr><td " + style + ">" + name + "</td><td>" + type + "</td><td>" + isRequired + "</td><td>" + desc + "</td></tr> ");
                if (entity.isHasChild()) {
                    html.append(getInParamTrPart(entity.getChildList()));
                }
            }
        }
        return html;
    }

    /**
     * 接口描述部分
     * @param subEntity
     * @return
     */
    private static StringBuilder getDescPart(SubEntity subEntity){
        StringBuilder reqHtml = new StringBuilder();
        Long generateTimeLong = subEntity.getGenerateTime();
        Date generateTime = new Date(generateTimeLong);
        String generateTimeFormated = new SimpleDateFormat(("yyyy-MM-dd HH:mm")).format(generateTime);

        reqHtml.append(" <span class='glyphicon glyphicon-minus'>请求地址</span> ");
        reqHtml.append(" <table class='table-div table table-bordered'><tbody> ");
        reqHtml.append(" <tr><td>生成时间</td><td>"+generateTimeFormated+"</td></tr> ");
        reqHtml.append(" <tr><td>数据格式</td><td>"+subEntity.getReqContentType()+"</td></tr> ");
        reqHtml.append(" <tr><td>请求地址</td><td>"+subEntity.getUrl()+"</td></tr> ");
        reqHtml.append(" </tbody></table> ");

        return reqHtml;
    }

    /**
     * 接口头部分
     * @param subEntity
     * @return
     */
    private static StringBuilder getUrlPart(SubEntity subEntity){

        StringBuilder reqHtml = new StringBuilder();
        reqHtml.append("  <div class='title-div btn btn-default'> " )
                .append("  <span class='arraw-span glyphicon glyphicon-chevron-up' style='display: none;'></span> ")
                .append("  <span class='arraw-span glyphicon glyphicon-chevron-down' style='display:inline;'></span> ");

        String method = subEntity.getMethod();
        String btnStyle = "btn-default";
        if("GET".equals(subEntity.getMethod())){
            btnStyle = "btn-success";
        }else if("POST".equals(subEntity.getMethod())){
            btnStyle = "btn-info";
        }
        reqHtml.append("  <button type='button' class='method-btn btn "+btnStyle+"'>"+method+"</button> ");
        reqHtml.append("  <span class='url-span'>"+subEntity.getUrl()+"</span> ")
                .append("  <span class='desc-span'>"+subEntity.getDesc()+"</span> ")
                .append(" </div> ");
        return reqHtml;
    }



}
